import { ResultFile, IPublicTypeProjectSchema } from '@alilc/lowcode-types';

import { IParseResult, IProjectBuilder, IProjectPlugins, IProjectTemplate, ISchemaParser } from '../types';
import { SchemaParser } from '../parser/SchemaParser';
import { createModuleBuilder } from './ModuleBuilder';

interface IModuleInfo {
  files: ResultFile[];
}

export class ProjectBuilder implements IProjectBuilder {
  /** 项目模板 */
  private template: IProjectTemplate;
  /** 项目插件 */
  private plugins: IProjectPlugins;
  /** Schema 解析器 */
  private schemaParser: ISchemaParser;
  /** 是否处于严格模式 */
  readonly inStrictMode: boolean;

  constructor(builderOptions) {
    let customBuilderOptions = builderOptions;
    const { plugins } = customBuilderOptions;
    this.template = { slots: { components: { path: ['src', 'components'] } } };
    this.plugins = plugins;
    this.schemaParser = new SchemaParser();
    this.inStrictMode = false;
  }
  async generateProject(originalSchema: IPublicTypeProjectSchema | string): Promise<any> {
    const { schemaParser } = this;
    const schema = typeof originalSchema === 'string' ? JSON.parse(originalSchema) : originalSchema;
    const parseResult: IParseResult = schemaParser.parse(schema);
    const moduleBuilder = createModuleBuilder({
      plugins: this.plugins.components,
      contextData: {
        inStrictMode: false,
        tolerateEvalErrors: true,
        evalErrorsHandler: '',
        extraContextData: {
          projectRemark: parseResult?.project?.projectRemark,
          template: this.template,
        },
      }
    });
    const buildResult: IModuleInfo[] = await Promise.all(parseResult.containers.map(async (containerInfo) => {
      // { files };
      return await moduleBuilder(containerInfo);
    }));

    return {
      buildResult,
      parseResult
    };
  }
}

export function createProjectBuilder(initOptions: any) {
  return new ProjectBuilder(initOptions);
}
